﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using ProgNetUtils;
using System.Drawing.Design;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraTab;
using DevExpress.XtraBars;

namespace ProgNetExtensions.LanguageExt
{
    [ProvideProperty("LngText", typeof(object))]
    [ProvideProperty("LngMgr", typeof(object))]
    [ProvideProperty("LngParams", typeof(object))]
    [ProvideProperty("LngPrefix", typeof(object))]
    [ProvideProperty("LngSurfix", typeof(object))]
    public class LanguageProvider : Component, IExtenderProvider, ISupportInitialize
    {
        private bool isInitialized = false;
        private Hashtable nameObjects = new Hashtable();

        public LanguageProvider()
        {
            Language.LanguageChanged += new EventHandler(Language_LanguageChanged);
        }

        void Language_LanguageChanged(object sender, EventArgs e)
        {
            foreach (object obj in nameObjects.Keys)
            {
                if (CanExtend(obj))
                {
                    LanguageHelper helper = nameObjects[obj] as LanguageHelper;
                    if (helper != null)
                    {
                        SetPropertyValue(obj);
                        helper.WasChanged = false;
                    }
                }
            }
        }

        #region LngText
        [Category("ProgNet Language")]
        [DisplayName("LngText")]
        public string GetLngText(object sender)
        {
            string result = string.Empty;
            LanguageHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as LanguageHelper;
                }
                else
                {
                    string str = GetDefaultLngText(sender);
                    if (str.IsNotEmpty())
                    {
                        helper = new LanguageHelper();
                        helper.LngText = str;
                        nameObjects.Add(sender, helper);
                    }
                }
            }
            if (helper != null)
                result = helper.LngText;
           
            return result;
        }

        public void SetLngText(object sender, string value)
        {
            LanguageHelper helper = null;
            
            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as LanguageHelper;
            }
            else
            {
                helper = new LanguageHelper();
                nameObjects.Add(sender, helper);
            }
            
            if (helper != null)
                helper.LngText = value;

            if (!PnInitialization.IsAppRunning)
                SetPropertyValue(sender);

        }
        #endregion

        #region LngMgr
        [Category("ProgNet Language")]
        [DisplayName("LngMgr")]
        public string GetLngMgr(object sender)
        {
            string result = string.Empty;
            LanguageHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as LanguageHelper;
                }
            }
            if (helper != null)
                result = helper.LngMgr;
            return result;
        }

        public void SetLngMgr(object sender, string value)
        {
            LanguageHelper helper = null;
            
            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as LanguageHelper;
            }
            else
            {
                helper = new LanguageHelper();
                nameObjects.Add(sender, helper);
            }
            
            if (helper != null)
                helper.LngMgr = value;
        }
        #endregion

        #region LngParams
        [Category("ProgNet Language")]
        [DisplayName("LngParams")]
        public string[] GetLngParams(object sender)
        {
            string[] result = null;
            LanguageHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as LanguageHelper;
                }
            }
            if (helper != null)
                result = helper.LngParams;
            return result;
        }

        public void SetLngParams(object sender, string[] value)
        {
            LanguageHelper helper = null;
            
            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as LanguageHelper;
            }
            else
            {
                helper = new LanguageHelper();
                nameObjects.Add(sender, helper);
            }
            
            if (helper != null)
                helper.LngParams = value;
        }
        #endregion

        #region LngPrefix
        [Category("ProgNet Language")]
        [DisplayName("LngPrefix")]
        public string GetLngPrefix(object sender)
        {
            string result = string.Empty;
            LanguageHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as LanguageHelper;
                }
            }
            if (helper != null)
                result = helper.LngPrefix;
            return result;
        }

        public void SetLngPrefix(object sender, string value)
        {
            LanguageHelper helper = null;
            
            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as LanguageHelper;
            }
            else
            {
                helper = new LanguageHelper();
                nameObjects.Add(sender, helper);
            }
            
            if (helper != null)
                helper.LngPrefix = value;
        }
        #endregion

        #region LngSurfix
        [Category("ProgNet Language")]
        [DisplayName("LngSurfix")]
        public string GetLngSurfix(object sender)
        {
            string result = string.Empty;
            LanguageHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as LanguageHelper;
                }
            }
            if (helper != null)
                result = helper.LngSurfix;
            return result;
        }

        public void SetLngSurfix(object sender, string value)
        {
            LanguageHelper helper = null;
            
            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as LanguageHelper;
            }
            else
            {
                helper = new LanguageHelper();
                nameObjects.Add(sender, helper);
            }
            
            if (helper != null)
                helper.LngSurfix = value;
        }
        #endregion

        private LanguageHelper GetHelperByName(string name)
        {
            foreach (object obj in nameObjects.Keys)
            {
                if (name == obj.GetObjectName())
                    return nameObjects[obj] as LanguageHelper;
            }
            return null;
        }

        #region virtual
        protected virtual string GetDefaultLngText(object sender)
        {
            if (sender is GridColumn)
                return (sender as GridColumn).FieldName;
            if (sender is GridView)
                return (sender as GridView).LevelName;
            return null;

        }
        protected virtual string GetDefaultProperty(object sender)
        {
            string[] properties = new string[]{
                "Text",
                "Caption",
                "ViewCaption"};
            foreach (string p in properties)
            {
                if (sender.HasProperty(p))
                    return p;
            }
            return string.Empty;

        }
        protected virtual void SetPropertyValue(object sender)
        {
            string lngText = GetLngText(sender);
            string lngMgr = GetLngMgr(sender);
            string[] lngParams = GetLngParams(sender);
            string lngPrefix = GetLngPrefix(sender);
            string lngProperty = GetDefaultProperty(sender);
            string lngSurfix = GetLngSurfix(sender);
            if (lngText.IsNotEmpty())
            {
                string text = "";
                if (PnInitialization.IsAppRunning)
                {
                    if (Language.Current != null)
                        text = Language.Current.GetLngString(lngMgr, lngText, lngParams);
                    else
                        text = "No Language";
                }
                else
                    text = "Lng[" + lngText + "]";

                if (sender is RadioGroup)
                {
                    foreach (RadioGroupItem item in (sender as RadioGroup).Properties.Items)
                    {
                        if (PnInitialization.IsAppRunning)
                        {
                            if (Language.Current != null)
                                text = Language.Current.GetLngString(lngMgr, lngText + "_" + item.Value.AsString(), lngParams);
                            else
                                text = "No Language";
                        }
                        else
                            text = "Lng[" + lngText+"_"+item.Value.AsString() + "]";

                        item.Description = text;
                    }
                }
                if (sender.HasProperty(lngProperty))
                {
                    sender.SetProperty(lngProperty, lngPrefix + text + lngSurfix);
                }
                if (sender is GridView)
                {
                    GridView v = (sender as GridView);
                    if (v.GridControl.LevelTree.Find(v) != null)
                    {
                        if (v.GridControl.LevelTree.Find(v).Parent != null)
                        {
                            GridView parent = v.GridControl.LevelTree.Find(v).Parent.LevelTemplate as GridView;
                            if (parent != null)
                            {
                                ReExpandAllViews(parent);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Collapses and expands all expanded views.
        /// When view is expanded ViewCaption is changed
        /// </summary>
        /// <param name="parent"></param>
        protected void ReExpandAllViews(GridView parent)
        {
            if (parent != null)
            {
                for (int i = 0; i < parent.RowCount; i++)
                {
                    if (parent.GetMasterRowExpanded(i))
                    {
                        int relCount = parent.GetRelationCount(i);
                        for (int j = 0; j < relCount; j++)
                        {
                            ReExpandAllViews(parent.GetDetailView(i, j) as GridView);
                        }
                        parent.SetMasterRowExpanded(i, false);
                        parent.SetMasterRowExpanded(i, true);
                    }
                }
            }
        }

        #endregion

        #region IExtenderProvider Members

        public virtual bool CanExtend(object extendee)
        {
            if (extendee is Label ||
                extendee is LabelControl ||
                extendee is Form ||
                extendee is XtraForm || 
                extendee is Button ||
                extendee is SimpleButton ||
                extendee is GridColumn || 
                extendee is GridView ||
                extendee is CheckEdit ||
                extendee is MarqueeProgressBarControl||
                extendee is PanelControl ||
                extendee is BarItem ||
                extendee is RadioGroup)
            {
                return true;
            }
            
            return false;
        }

        #endregion

        #region ISupportInitialize Members

        public void BeginInit()
        {
           
        }

        public void EndInit()
        {
            isInitialized = true;
            foreach (object obj in nameObjects.Keys)
            {
                if (CanExtend(obj))
                {
                    LanguageHelper helper = nameObjects[obj] as LanguageHelper;
                    if (helper != null)
                    {
                        if (helper.WasChanged)
                        {
                            SetPropertyValue(obj);
                            helper.WasChanged = false;
                        }
                    }
                }
            }
        }

        #endregion
    }
    public class LanguageHelper
    {
        public string _LngText;
        public string _LngMgr;
        public string[] _LngParams;
        public string _LngPrefix;
        public string _LngSurfix;
        private bool _WasChanged = true;

        public string LngText
        {
            get { return _LngText; }
            set
            {
                _LngText = value;
                WasChanged = true;
            }
        }
        public string LngMgr
        {
            get { return _LngMgr; }
            set
            {
                _LngMgr = value;
                WasChanged = true;
            }
        }
        public string[] LngParams
        {
            get { return _LngParams; }
            set
            {
                _LngParams = value;
                WasChanged = true;
            }
        }
        public string LngPrefix
        {
            get { return _LngPrefix; }
            set
            {
                _LngPrefix = value;
                WasChanged = true;
            }
        }
        public string LngSurfix
        {
            get { return _LngSurfix; }
            set
            {
                _LngSurfix = value;
                WasChanged = true;
            }
        }
        public bool WasChanged
        {
            get { return _WasChanged; }
            set { _WasChanged = value; }
        }

        
    }
}
